using System;
using System.IO;
using OracleInternal.Json.Binary;
using OracleInternal.Json.Common;

namespace OracleInternal.Json.Sql
{
	internal sealed class OracleJsonFactory
	{
		private const bool DISABLE_GENERATOR_POOL = false;

		private const int DEFAULT_BUFFER_SIZE = 8192;

		private OsonGeneratorStatePool generatorPool = new OsonGeneratorStatePool();

		public OracleJsonValue createJsonBinaryValue(Stream inStream)
		{
			ByteBuffer inBuffer = ByteBuffer.Wrap(readInputStream(inStream));
			return createJsonBinaryValue(inBuffer);
		}

		public OracleJsonValue createJsonBinaryValue(ByteBuffer inBuffer)
		{
			OsonContext osonContext = new OsonContext(new OsonBuffer(inBuffer));
			return (OracleJsonValue)OsonStructure.GetValueInternal(osonContext.GetHeader().GetTreeSegmentOffset(), osonContext.GetFactory(), osonContext);
		}

		public OracleJsonGenerator createJsonBinaryGenerator(Stream outStream)
		{
			return new OsonGenerator(generatorPool, outStream);
		}

		public OracleJsonGenerator createJsonTextGenerator(Stream outStream)
		{
			return new OracleJsonSerializer(outStream);
		}

		public OracleJsonGenerator createJsonTextGenerator(TextWriter outWriter)
		{
			return new OracleJsonSerializer(outWriter);
		}

		public OracleJsonObject createObject()
		{
			return new OracleJsonObject();
		}

		public OracleJsonArray createArray()
		{
			return new OracleJsonArray();
		}

		public OracleJsonObject createObject(OracleJsonObject other)
		{
			return new OracleJsonObject(other);
		}

		public OracleJsonArray createArray(OracleJsonArray other)
		{
			return new OracleJsonArray(other);
		}

		public OracleJsonString createString(string value)
		{
			return new OracleJsonString(value.ToCharArray());
		}

		public OracleJsonDecimal createDecimal(decimal value)
		{
			return new OracleJsonDecimal(value);
		}

		public OracleJsonDecimal createDecimal(int value)
		{
			return new OracleJsonDecimal(value);
		}

		public OracleJsonDecimal createDecimal(long value)
		{
			return new OracleJsonDecimal(value);
		}

		public OracleJsonFloat createFloat(float value)
		{
			return new OracleJsonFloat(value);
		}

		public OracleJsonDouble createDouble(double value)
		{
			return new OracleJsonDouble(value);
		}

		public OracleJsonBinary createBinary(byte[] value)
		{
			return new OracleJsonBinary(value, isId: false);
		}

		public OracleJsonValue createBoolean(bool value)
		{
			if (!value)
			{
				return OracleJsonValue.FALSE;
			}
			return OracleJsonValue.TRUE;
		}

		public OracleJsonValue createNull()
		{
			return OracleJsonValue.NULL;
		}

		public OracleJsonTimestamp createTimestamp(DateTime value)
		{
			return new OracleJsonTimestamp(value);
		}

		public OracleJsonDate createDate(DateTime i)
		{
			return new OracleJsonDate(i);
		}

		public OracleJsonIntervalDS createIntervalDS(TimeSpan d)
		{
			return new OracleJsonIntervalDS(d);
		}

		public OracleJsonIntervalYM createIntervalYM(Period p)
		{
			return new OracleJsonIntervalYM(p);
		}

		private static byte[] readInputStream(Stream inStream)
		{
			try
			{
				byte[] buffer = new byte[8192];
				MemoryStream memoryStream = new MemoryStream();
				int count;
				while ((count = inStream.Read(buffer, 0, 8192)) != -1)
				{
					memoryStream.Write(buffer, 0, count);
				}
				inStream.Close();
				return memoryStream.ToArray();
			}
			catch (IOException ex)
			{
				throw OracleJsonExceptions.IO.Create(OracleJsonExceptions.ORACLE_FACTORY, ex);
			}
		}
	}
}
